package com.atguigu.gulimall.auth.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import com.atguigu.common.utils.HttpUtils;
import com.atguigu.common.utils.R;
import com.atguigu.common.utils.ResourcesUtil;
import com.atguigu.gulimall.auth.feign.MemberFeignService;
import com.atguigu.common.vo.MemberRespVo;
import com.atguigu.gulimall.auth.vo.SocialUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * 处理社交登录请求
 */
@Slf4j
@Controller
public class OAuth2Controller {
    @Autowired
    private MemberFeignService memberFeignService;

    @GetMapping("/oauth2.0/weibo/success")
    public String weibo(@RequestParam("code") String code, HttpSession session, HttpServletResponse servletResponse, HttpServletRequest request) throws Exception {

        Map<String, String> map = new HashMap<>();
        map.put("client_id", "3375990350");
        map.put("client_secret", "380c5b0010c2b8e9c5727c28b177039d");
        map.put("grant_type", "authorization_code");
        map.put("redirect_uri", "http://auth.gulimall.com/oauth2.0/weibo/success");
        map.put("code", code);
        // 1、根据code换取accessToken
        HttpResponse response = HttpUtils.doPost("https://api.weibo.com", "/oauth2/access_token", "post", new HashMap<String, String>(), null, map);
        // 2、处理
        if (response.getStatusLine().getStatusCode() == 200) {
            // 获取accessToken成功
            String json = EntityUtils.toString(response.getEntity());
            SocialUser socialUser = JSON.parseObject(json, SocialUser.class);
            // 为了能够支持不同的社交登录工具，在SocialUser类中增加了属性ToolType
            socialUser.setToolType("微博");
            // 知道当前是哪个社交用户
            // 1）、如果用户是第一次进入网站，就要自动注册进来(为当前社交用户生成一个会员信息账号，以后这个社交帐号就对应指定的会员)
            // 登录或者注册这个社交用户
            R oauthlogin = this.memberFeignService.oauthlogin(socialUser);
            if (oauthlogin.getCode() == 0) {
                MemberRespVo data = oauthlogin.getData("data", new TypeReference<MemberRespVo>() {});
                log.info("登录成功：用户：{}", data.toString());
                /**
                 * 第一次使用session，命令浏览器保存JSESSIONID的value值
                 * 以后浏览器访问这个网站就会带上这个cookie
                 * 子域之间：gulimall.com    auth.gulimall.com   order.gulimall.com
                 * 发卡的时候（指定域名为父域名），即使是子域系统发的卡，也能让父域直接使用
                 */
                // TODO 1、默认发的令牌。session=xxxx。作用域：当前域：（解决子域session共享问题）
                // TODO 2、使用json的序列化方式来序列化对象数据到redis中
                session.setAttribute("loginUser", data);
                // 2、登录成功就跳回首页
                return "redirect:http://gulimall.com";
            } else {
                return "redirect:http://auth.gulimall.com/login.html";
            }
        } else {
            return "redirect:http://auth.gulimall.com/login.html";
        }
    }

    @GetMapping("/oauth2.0/alipay/success")
    public String alipay(@RequestParam("auth_code") String code, HttpSession session,
                         HttpServletResponse servletResponse, HttpServletRequest request) throws Exception {
        ResourcesUtil resourcesUtil = new ResourcesUtil("application.properties");
        //在支付宝创建的应用的id
        // String app_id = "2016102600765903";
        String app_id = resourcesUtil.getValue("alipay.app_id");

        // 商户私钥，您的PKCS8格式RSA2私钥
        String merchant_private_key = resourcesUtil.getValue("alipay.merchant_private_key");

        // 支付宝公钥,查看地址：https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
        String alipay_public_key = resourcesUtil.getValue("alipay.alipay_public_key");
        // 服务器[异步通知]页面路径  需http://格式的完整路径，不能加?id=123这类自定义参数，必须外网可以正常访问
        // 支付宝会悄悄的给我们发送一个请求，告诉我们支付成功的信息
        String notify_url = resourcesUtil.getValue("alipay.notify_url");

        // 页面跳转同步通知页面路径 需http://格式的完整路径，不能加?id=123这类自定义参数，必须外网可以正常访问
        //同步通知，支付成功，一般跳转到成功页
        String return_url = resourcesUtil.getValue("alipay.return_url");

        // 签名方式
        String sign_type = resourcesUtil.getValue("alipay.sign_type");

        // 字符编码格式
        String charset = resourcesUtil.getValue("alipay.charset");

        String timeout = "30m";

        // 支付宝网关； https://openapi.alipaydev.com/gateway.do
        String gatewayUrl = resourcesUtil.getValue("alipay.gatewayUrl");

        try {
            //1、根据支付宝的配置生成一个支付客户端
            AlipayClient alipayClient = new DefaultAlipayClient(gatewayUrl, app_id, merchant_private_key, "json",
                                                                charset, alipay_public_key, sign_type);
            AlipaySystemOauthTokenRequest requestAlipay = new AlipaySystemOauthTokenRequest();
            requestAlipay.setCode(code);
            requestAlipay.setGrantType("authorization_code");

            AlipaySystemOauthTokenResponse oauthTokenResponse = alipayClient.execute(requestAlipay);

            // 2、处理
            if (StringUtils.isEmpty(oauthTokenResponse.getAccessToken())) {
                return "redirect:http://auth.gulimall.com/login.html";
            }
            // 获取accessToken成功
            // String json = EntityUtils.toString(response.getEntity());
            // SocialUser socialUser = JSON.parseObject(json, SocialUser.class);
            String json = oauthTokenResponse.getBody();
            String code1 = oauthTokenResponse.getCode();
            String msg = oauthTokenResponse.getMsg();
            Map<String, String> params = oauthTokenResponse.getParams();
            String accessToken = oauthTokenResponse.getAccessToken();
            String alipayUserId = oauthTokenResponse.getAlipayUserId();
            String authTokenType = oauthTokenResponse.getAuthTokenType();
            String expiresIn = oauthTokenResponse.getExpiresIn();
            String reExpiresIn = oauthTokenResponse.getReExpiresIn();
            String refreshToken = oauthTokenResponse.getRefreshToken();
            String userId = oauthTokenResponse.getUserId();

            SocialUser socialUser = new SocialUser();
            socialUser.setAccess_token(accessToken);
            socialUser.setExpires_in(Long.parseLong(expiresIn));
            socialUser.setUid(alipayUserId);
            socialUser.setToolType("支付宝");
            // 知道当前是哪个社交用户
            // 1）、如果用户是第一次进入网站，就要自动注册进来(为当前社交用户生成一个会员信息账号，以后这个社交帐号就对应指定的会员)
            // 登录或者注册这个社交用户
            R oauthlogin = this.memberFeignService.oauthlogin(socialUser);
            if (oauthlogin.getCode() != 0) {
                return "redirect:http://auth.gulimall.com/login.html";
            }
            MemberRespVo data = oauthlogin.getData("data", new TypeReference<MemberRespVo>() {});
            log.info("登录成功：用户：{}", data.toString());
            /**
             * 第一次使用session，命令浏览器保存JSESSIONID的value值
             * 以后浏览器访问这个网站就会带上这个cookie
             * 子域之间：gulimall.com    auth.gulimall.com   order.gulimall.com
             * 发卡的时候（指定域名为父域名），即使是子域系统发的卡，也能让父域直接使用
             */
            // TODO 1、默认发的令牌。session=xxxx。作用域：当前域：（解决子域session共享问题）
            // TODO 2、使用json的序列化方式来序列化对象数据到redis中
            session.setAttribute("loginUser", data);
            // 2、登录成功就跳回首页
            return "redirect:http://gulimall.com";
        } catch (AlipayApiException e) {
            //处理异常
            e.printStackTrace();
        }
        return "redirect:http://auth.gulimall.com/login.html";
    }
}
